<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    body,
    html{
        height: 500%;
    }
    #app {
  width: 200px;
  margin: 0 auto;
  overflow: hidden;
  #box {
    display: flex;
    position: relative;
    img {
      width: 200px;
      height: 300px;
    }
  }

  .btns {
    text-align: center;
  }
}
</style>
<html>
    <div id="app">
        <section class="box">
            <img
                src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4c7b4883c1704286a9365575a2a1c05f~tplv-k3u1fbpfcp-watermark.image?">
    
            <img
                src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0acae783691649c9b36fa6bd64aa31d2~tplv-k3u1fbpfcp-watermark.image?">
    
            <img
                src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9c266e0576fd4632bec39228d81534e4~tplv-k3u1fbpfcp-watermark.image?">
    
            <img
                src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5e4b66351ea64b55a329f636c255a55b~tplv-k3u1fbpfcp-watermark.image?">
        </section>
        <div class='btns'>
            <button onclick="prev()">prev</button>
            <button onclick="next()">next</button>
        </div>
        
        <div class='btns'>
            <button onclick="autoPlay()">autoPlay</button>
            <button onclick="stopAutoPlay()">stopAutoPlay</button>
        </div>
    </div>
</html>
<body>
    <script>
        //洗牌算法
        // function washArray(array){
        //     for(let i=0 ; i < array.length -1 ;i++){
        //         const j = Math.floor(Math.random() * (i + 1 ));
        //         [array[i],array[j]] = [array[j],array[i]]
        //     } 
        //     return array
        // }

        // let array = [1,2,3,4,5]
        // let res = washArray(array)
        // console.log(res);



        //请设计一个 combinations 函数，它接收一个数字数组，要求返回这些数字的所有可能组合情况。
        // function combinations(array){
        //     let arr = [[]]
        //     for(n of array){
        //         let arrLength = arr.length
        //         for(let i = 0 ; i < arrLength ; i++){
        //             arr.push([...arr[i],n])
        //         }
        //     }
        //     return arr
        // }
        // let array = [1,2,3]
        // let newArray = combinations(array)
        // console.log(newArray);


        //数组扁平化
        // 递归方法：
        // function flatten(array){
        //     let arr = []
        //     array.forEach(element => {
        //         if(Array.isArray(element)){
        //             arr = arr.concat(flatten(element))
        //         }else{
        //             arr.push(element)
        //         }
        //     });
        //     return arr
        // }
        // let array = [1,[1,2,5],2,[1,[32,44]]]
        // let res = flatten(array)
        // console.log(res);
        // 非递归实现方案，用栈。
        // function flatten(array){
        //     let arr = []
        //     let stack = [...array]
        //     while(stack.length){
        //         let num = stack.pop()
        //         if(Array.isArray(num)){
        //             stack.push(...num)
        //         }else{
        //             arr.push(num)
        //         }
        //     }
        //     return arr
        // }
        // ES6方法：
        // function flatten(array){
        //     return array.flat(Infinity)
        // }



        // 实现Sum函数链式调用计算多数之和
        // function sum(init){
        //     this.total = init
        // }
        // sum.prototype.add = function(num){
        //     this.total += num
        //     return this
        // }
        // let SUM = new sum(1)
        // SUM.add(2).add(5)
        // console.log(SUM.total);

        // function sum(...args){
        //     let currentSum = args.reduce((acc, value) => acc + value, 0);
        //     function sumof(...nums){
        //         currentSum += nums.reduce((nvlu,ovlu) => nvlu + ovlu , 0)
        //         return sumof
        //     }
        //     sumof.sums = function(){
        //         return currentSum
        //     }
        //     return sumof
        // }
        // let res = sum(1,2)(4)(5).sums()
        // console.log(res);



        // 实现将对象数组转换为对象
        // function changeArrToObject(arr){
        //     return arr.reduce((pre , {key , val}) => {
        //         pre[key] = val
        //         return pre
        //     },{})
        // }
        // let arr = [{key:'real',val:'name'},{ key: 'Real', val: 'Name' }]
        // let Obj = changeArrToObject(arr)
        // console.log(Obj);



        // 编写函数，每次返回下一个质数（Prime number）
        // function isPrime(num){
        //     for( let i=2 ; i < num ; i++){
        //         if(num % i == 0){return false}
        //     }
        //     return num > 1
        // }
        // function getPrime(){
        //     let currentNum = 2
        //     return function(){
        //         while(true){
        //             if(isPrime(currentNum)){
        //                 let prime = currentNum
        //                 currentNum++
        //                 return prime
        //             }else{
        //                 currentNum++
        //             }
        //         }
        //     }
        // }
        // let nextPrime = getPrime()
        // console.log(nextPrime());
        // console.log(nextPrime());
        // console.log(nextPrime());
        // console.log(nextPrime());
        // console.log(nextPrime());
        // console.log(nextPrime());



        // 列表转树
        // function listToTree(list){
        //     let res = []
        //     list.forEach(element => {
        //         let parent = list.find((item) => {
        //             return item.id == element.parentId
        //         })
        //         if(parent){
        //             parent.children = parent.children || []
        //             parent.children.push(element)
        //         }else{
        //             res.push(element)
        //         }
        //     });
        //     return res
        // }
        // function listToTree2(list) {
        //     let obj = {}
        //     list.forEach(element => {
        //         obj[element.id] = element
        //     });
        //     let parentList = []
        //     list.forEach((item)=>{
        //         let parent = obj[item.parentId]
        //         if(parent){
        //             parent.children = parent.children || []
        //             parent.children.push(item)
        //         }else{
        //             parentList.push(item)
        //         }
        //     })
        //     return parentList
        // }
        // const list = [
        //         { id: 1, name: 'Node 1', parentId: null },
        //         { id: 2, name: 'Node 2', parentId: 1 },
        //         { id: 3, name: 'Node 3', parentId: 1 },
        //         { id: 4, name: 'Node 4', parentId: 2 },
        //         { id: 5, name: 'Node 5', parentId: 2 },
        //         { id: 6, name: 'Node 6', parentId: 3 },
        //         { id: 7, name: 'Node 7', parentId: 3 },
        //         { id: 8, name: 'Node 8', parentId: 4 }
        //     ];
        //     console.time('111')
        //     let res = listToTree(JSON.parse(JSON.stringify(list)))
        //     console.log(res);
        //     console.timeEnd('111')
        //     console.time('222')
        //     let res2 = listToTree2(JSON.parse(JSON.stringify(list)))
        //     console.log(res2);
        //     console.timeEnd('222')



        // 树形结构转成列表
        // function treeToList(data){
        //     let res = []
        //     const change = (tree) => {
        //         tree.forEach(element => {
        //             if(element.children){
        //                 change(element.children)
        //                 delete element.children
        //                 res.push(element)
        //             }else{
        //                 res.push(element)
        //             }
        //         });
        //     }
        //     change(data)
        //     return res
        // }
        // let tree = [
        //         {
        //             id: 1,
        //             text: "节点1",
        //             parentId: 0,
        //             children: [
        //                 {
        //                     id: 2,
        //                     text: "节点1_1",
        //                     parentId: 1,
        //                 },
        //             ],
        //         },
        //     ]
        // let res = treeToList(tree)
        // console.log(res);



        // 如何判断两个数组的内容是否相等
        // function compArrsIsEqual(arr1,arr2){
        //     if(arr1.length !== arr2.length){
        //         return false
        //     }
        //     function count(arr){
        //         const countMap = new Map()
        //         for(const item of arr){
        //             countMap.set(item , (countMap.get(item) || 0 ) + 1 )
        //         }
        //         return countMap
        //     }
        //     let countArr1 = count(arr1)
        //     let countArr2 = count(arr2)
        //     for(const [key , value] of countArr1){
        //         if(countArr2.get(key) !== value){
        //             return false
        //         }
        //     }
        //     return true
        // }
        // const array1 = ["apple", "banana", "cherry", "banana", 1, '1', '11', 11];
        // const array2 = ["banana", "apple", "banana", "cherry", '1', 1, '11', 11];
        // let res = compArrsIsEqual(array1, array2)
        // console.log(res);



        // 数组去重
        // 1.set
        // let arr = [1,2,3,4,1,14]
        // let res = Array.from(new Set(arr))
        // console.log(res);
        // 2.indexof
        // function indexofArr(arr){
        //     let res = []
        //     for(let i = 0 ; i < arr.length ; i++){
        //         if(res.indexOf(arr[i]) === -1){
        //             res.push(arr[i])
        //         }
        //     }
        //     return res
        // }
        // let res = indexofArr(arr)
        // console.log(res);
        // 3.includes
        // function includesArr(arr){
        //     let res = []
        //     for(let i = 0 ; i < arr.length ; i++){
        //         if(!res.includes(arr[i])){
        //             res.push(arr[i])
        //         }
        //     }
        //     return res
        // }
        // let res = includesArr(arr)
        // console.log(res);
        // 4.利用filter，并结合indexOf
        // function fillterArr(arr){
        //     let res = arr.filter((item,index) => {
        //         return arr.indexOf(item) === index
        //     })
        //     return res
        // }
        // let res = fillterArr(arr)
        // console.log(res);
        // 5.利用对象
        // function objArr(arr){
        //     let obj = {}
        //     arr.forEach(element => {
        //         if(!obj[element]){
        //             obj[element] = true
        //         }
        //     });
        //     return Object.keys(obj)
        // }
        // console.log(objArr(arr));
        // 6.利用Map()
        // function mapArr(arr){
        //     let map = new Map()
        //     arr.forEach(element => {
        //         if(!map.has(element)){
        //             map.set(element)
        //         }
        //     });
        //     return [...map.keys()]
        // }
        // console.log(mapArr(arr));



        // 数组交集
        // 1.利用indexOf
        // function indexOfArr(arr1,arr2){
        //     let res = []
        //     arr1.forEach(element => {
        //         if(arr2.indexOf(element) !== -1){
        //             res.push(element)
        //         }
        //     });
        //     return res
        // }
        let arr1 = [1,2,3,4,5,7]
        let arr2 = [1,24,6,3,6,3]
        // console.log(indexOfArr(arr1,arr2));
        // 2.利用include
        // function includesArr(arr1,arr2){
        //     let res = []
        //     arr1.forEach(element => {
        //         if (arr2.includes(element)) {
        //             res.push(element)
        //         }
        //     });
        //     return res
        // }
        // console.log(includesArr(arr1,arr2));
        // 3.利用filter并结合indexOf、include
        // function filterArr(arr1,arr2){
        //     let res = arr1.filter((item) => {
        //         return arr2.includes(item)
        //     })
        //     return res
        // }
        // function fillterArr2(arr1,arr2){
        //     let res = arr1.filter((item) => {
        //         return arr2.indexOf(item) != -1
        //     })
        //     return res
        // }
        // console.log(filterArr(arr1,arr2));
        // console.log(fillterArr2(arr1,arr2));



        // 数组差集
        // 1.利用indexOf
        // function indexOfArr(arr1,arr2){
        //     let res = []
        //     arr1.forEach(element => {
        //         if(arr2.indexOf(element) == -1){
        //             res.push(element)
        //         }
        //     });
        //     res = Array.from(new Set(res))
        //     return res
        // }
        // console.log(indexOfArr(arr2,arr1));
        // 2.利用include
        // function includesArr(arr1,arr2){
        //     let res = []
        //     arr1.forEach(element => {
        //         if(!arr2.includes(element)){
        //             res.push(element)
        //         }
        //     });
        //     res = Array.from(new Set(res))
        //     return res
        // }
        // console.log(includesArr(arr1,arr2));



        // 类数组转数组 arguments伪数组
        // Array.prototype.slice.call(arrayLike);
        // Array.prototype.splice.call(arrayLike,0);
        // Array.prototype.concat.apply([],arrayLike);
        // Array.from(arrayLike);
        // [...arrayLike]


        // sort排序
        // 1.对数字进行排序，简写
        // let numArr = [1,3,2,4,5]
        // numArr.sort((a,b) => a - b ) //a - b表示从小到大
        // console.log(numArr);
        // 2.对字母进行排序，简写
        // let charArr = ['c','b','a','e']
        // charArr.sort((a,b) => {
        //     if(a > b) return 1  //a > b返回1表示小字母在前
        //     if(a < b) return -1
        //     return 0
        // })
        // console.log(charArr);



        // 冒泡排序
        // function popSort(arr){
        //     for(let i = 0; i < arr.length - 1 ; i++){
        //         for(let j = 0; j < arr.length - 1 - i ; j++){
        //             if(arr[j] > arr[j+1]){
        //                 let temp = arr[j]
        //                 arr[j] = arr[j+1]
        //                 arr[j+1] = temp
        //             }
        //         }
        //     }
        //     return arr
        // }
        // let popArr = [2,3,4,1,77,23,13]
        // console.log(popSort(popArr));


        // 手写快速排序
        // function quickSort(arr,startIndex = 0){
        //     if(arr.length <= 1) {
        //         return arr
        //     }
        //     let rightNums = [],
        //     leftNums = [],
        //     startNum = arr.splice(startIndex,1)[0]
        //     for(let i = 0; i < arr.length; i++){
        //         if(arr[i] < startNum){
        //             leftNums.push(arr[i])
        //         }else{
        //             rightNums.push(arr[i])
        //         }
        //     }
        //     return [...quickSort(leftNums),startNum,...quickSort(rightNums)]
        // }
        // let quickArr = [5,1,778,2,44,64,343]
        // console.log(quickSort(quickArr));



        // 千分位分割，编写函数convert(money) 
        // function convert(money){
        //     let intResult = []     //整数部分
        //     let negativeFlag = ''  //负号部分
        //     let tail = ''          //小数部分
        //     let moneyArr = [...String(money)]  
        //     //判断是不是负数
        //     if(moneyArr[0] == '-'){
        //         negativeFlag = '-'
        //         moneyArr.shift()
        //     }
        //     //判断有没有小数点
        //     let dotIndex = moneyArr.indexOf('.')
        //     if(dotIndex >= -1){
        //         tail = moneyArr.splice(dotIndex , moneyArr.length - dotIndex).join('')
        //     }
        //     //处理整数部分
        //     let reverseArray = moneyArr.reverse()
        //     for(let i = 0; i < reverseArray.length; i++){
        //         if((i + 1) % 3 == 0 && (i + 1) < reverseArray.length){
        //             intResult[i] = ',' + reverseArray[i]
        //         }else{
        //             intResult[i] = reverseArray[i]
        //         }
        //     }
        //     return negativeFlag + intResult.reverse().join("") + tail
        // }
        // console.log(convert(1233556.43434555));



        // 封装一个数据类型判断函数
        function getType(value){
            if(value === null){
                return value + ''
            }
            if(typeof value === 'object'){
                let valueClass = Object.prototype.toString.call(value)
                console.log(valueClass);  //[object Array]
                if(valueClass.includes('object')){
                    return value.constructor.name.toLowerCase();
                }else{
                    let type = valueClass.split(' ')[1].split('')
                    type.pop()
                    type = type.join('')
                    return type
                }
            }else{
                return typeof value
            }
        }
        function getType(data) {
                //用于判断基础类型
                let type = typeof data;
                if (type !== "object") {
                    //要是基础类型就直接返回
                    return type
                }
                //要是Object类型就进行判断
                return Object.prototype.toString.call(data).slice(8, -1)
            }
        // console.log(getType([1]));



        // 手写reduce    应该要封装一个遍历加的函数，实现递归调用，来实现多维数组的累加
        Array.prototype.myReduce = function(callback , initValue){
            const arr = this
            let total = initValue ? initValue : arr[0]
            let startIndex = initValue ? 0 : 1
            for(let i = startIndex; i < arr.length; i++){
                if(Array.isArray(arr[i])){
                    for(let j = 0; j < arr[i].length; j++){
                        total = callback(total, arr[i][j])
                    }
                }else{
                    total = callback(total, arr[i])
                }
            }
            return total
        }
        // let arr = [1,4,5,7,[1,4,5]]
        // console.log(arr.myReduce((total , val) => {
        //     return total + val
        // },0));



        // 手写 instanceof
        function myInstanceof(left,right){
            let leftValue = left.__proto__
            let rightValue = right.prototype
            while (true) {
                if(leftValue === null){
                    return false
                }
                if(leftValue == rightValue){
                    return true
                }
                leftValue = left.__proto__
            }
        }


        // 手写 new
        function myNew(com , ...args){
            let A = {}                       //空对象
            Object.setPrototypeOf(A , com)   //原型指向
            let B = com.apply(A , ...args)   //this指向变化，执行com构造函数
            const newObj = B instanceof Object ? B : A  //确定实例对象
            return newObj                    //返回实例对象
        }



        // 手写 js浅拷贝、深拷贝
        // 浅拷贝
        function shallowCopy(obj){
            if(!obj || typeof obj !== 'object') return
            let newObj = Array.isArray(obj) ? [] : {}
            for( let key in obj ){
                if(obj.hasOwnProperty(key)){
                    newObj[key] = obj[key]
                }
            }
            return newObj
        }
        // 深拷贝
        function deepCopy(obj){
            if (!obj || typeof obj !== 'object') return
            let newObj = Array.isArray(obj) ? [] : {}
            for(let key in obj){
                if(obj.hasOwnProperty(key)){
                    newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
                }
            }
        }



        // 手写节流、防抖
        // 节流：就是单位时间内不管触发多少次函数，只固定执行一次函数
        function throttle(func , wait){
            let context , args
            let prev = 0
            return function(){
                let now = +new Date()
                context = this
                args = arguments
                if(now - prev > wait){
                    func.apply(context , args)
                    prev = now
                }
            }
        }
        // 防抖
        function debounce(func , wait){
            let context , args
            let timer = null
            return function(){
                context = this
                args = arguments
                if(timer){
                    clearTimeout(timer)
                }else{
                    timer = setTimeout(() => {
                        func.apply(context , args)
                    },wait)
                }
            }
        }



        // 手写call、apply、bind
        // call
        Function.prototype.mycall = function(context = window){
            if(typeof this !== 'function'){
                console.error('type error')
            }
            let args = [...arguments].slice(1)
            let result = null
            context.fn = this
            result = context.fn(...args)
            delete context.fn
            return result
        }
        // apply
        Function.prototype.myApply = function(context = window){
            if(typeof this !== 'function'){
                console.error('type error')
            }
            let args = [...arguments][1]
            let result = null
            context.fn = this
            if(args){
                context.fn(...args)
            }else{
                context.fn()
            }
            delete context.fn
            return result
        }
        // bind
        Function.prototype.myBind = function(context = window){
            if(typeof this !== 'function'){
                throw new Error('type')
            }
            let args = [...arguments].slice(1)
            let fn = this
            return function Fn(){
                return fn.apply(this instanceof Fn ? this : context , args.concat(...arguments))
            }
        }



        // 手写函数柯里化
        function curry(fn , args){
            // 获取函数需要的参数长度
            let length = fn.length
            args = args || []
            return function(){
                let subArgs = args.slice(0)
                // 拼接得到现有的所有参数
                for (let i = 0; i < arguments.length; i++) {
                    subArgs.push(arguments[i]);
                }
                // 判断参数的长度是否已经满足函数所需参数的长度
                if(subArgs.length >= length){
                    // 如果满足，执行函数
                    return fn.apply(this , subArgs)
                }else{
                    // 如果不满足，递归返回科里化的函数，等待参数的传入
                    return curry.call(this, fn, subArgs);
                }
            }
        }



        // 手写 EventBus
        class EventBus{
            constructor(){
                // 存储事件及其对应的回调函数列表
                this.events = {}
            }
            // 订阅事件
            subscribe( eventName , callback ){
                this.events[eventName] = this.events[eventName] || []
                this.events[eventName].push(callback)
            }
            // 发布事件
            publish( eventName , data ){
                if( this.events[eventName] ){
                    this.events[eventName].forEach((callback) => {
                        callback(data)
                    })
                }
            }
             // 取消订阅事件
            unsubscribe( eventName , callback ){
                this.events[eventName].filter((cb) => {
                    return cb != callback
                })
            }
            // 添加一次性的事件监听器 
            once(eventName, callback) {
                const onceCallback = data => {
                    callback(data); // 执行回调函数 
                    this.off(eventName, onceCallback); // 在执行后取消订阅该事件 
                };
                this.on(eventName, onceCallback);
            }
        }
            // 创建全局事件总线对象
            // const eventBus = new EventBus();
            // const callback1 = data => {
            //     console.log('Callback 1:', data);
            // };
            // const callback2 = data => {
            //     console.log('Callback 2:', data);
            // };
            // // 订阅事件
            // eventBus.subscribe('event1', callback1);
            // eventBus.subscribe('event1', callback2);
            // eventBus.once('event1', onceCallback);
            // // 发布事件
            // eventBus.publish('event1', 'Hello, world!');
            // // 输出：
            // // Callback 1: Hello, world!
            // // Callback 2: Hello, world!
            // // 取消订阅事件
            // eventBus.unsubscribe('event1', callback1);
            // // 发布事件
            // eventBus.publish('event1', 'Goodbye!');
            // 输出：
            // Callback 2: Goodbye!



        // 封装通用的事件侦听器函数
        const EventUtils = {
            // 添加事件
            addEvent: function (element, type, handler) {
                if (element.addEventListener) {
                    element.addEventListener(type, handler, false);
                } else if (element.attachEvent) {
                    element.attachEvent("on" + type, handler);
                } else {
                    element["on" + type] = handler;
                }
            },
            // 移除事件
            removeEvent: function (element, type, handler) {
                if( element.removeEventListener ){
                    element.removeEventListener(type, handler, false);
                }else if(element.detachEvent){
                    element.detachEvent("on" + type, handler);
                } else {
                    element["on" + type] = null
                }
            },
            // 获取事件目标
            getTarget: function (event) {
                return event.tatget || event.srcElement
            },
            // 获取 event 对象的引用，取到事件的所有信息，确保随时能使用 event
            getEvent: function (event) {
                return event || window.event;
            },
            // 阻止事件（主要是事件冒泡，因为 IE 不支持事件捕获）
            stopPropagation: function (event) {
                if (event.stopPropagation) {
                    event.stopPropagation();
                } else {
                    event.cancelBubble = true;
                }
            },
            // 取消事件的默认行为
            preventDefault: function (event) {
                if (event.preventDefault) {
                    event.preventDefault();
                } else {
                    event.returnValue = false;
                }
            },
        }



        // 实现Promise.all
        function allPromise(promises){
            return new Promise((resolve , reject) => {
                if(promises.length == 0){
                    resolve([])
                }else{
                    const res = []
                    let count = 0
                    for( let i = 0; i < promises.length; i++){
                        Promise.resolve(promises[i])
                        .then((data) => {
                            res[i] = data
                            count++
                            if(count == promises.length){
                                resolve(res)
                            }
                        })
                        .catch((err) => {
                            reject(err)
                        })
                    }
                }
            })
        }
        // 测试
            // const promise1 = Promise.resolve(5);
            // const promise2 = 4;
            // const promise3 = new Promise((resolve, reject) => {
            //     setTimeout(resolve, 100, "AK、DADADA");
            // });

            // allPromise([promise1, promise2, promise3]).then((values) => {
            //     console.log(values); //[5, 4, "AK、DADADA"]
            // });



        // 手写实现双向绑定(快手)
        
        


        //图片懒加载
        function lazyload(){
            let viewHeight = document.body.viewHeight
            let img = document.querySelectorAll('img[data-src]')
            img.forEach(item => {
                if(item.dataset.src == '') return
                let rect = item.getBoundingClientRect()
                if(rect.bottom > 0 && rect.top < viewHeight){
                    item.src = item.dataset.src
                    item.removeAttribute('data-src')
                }
            })
        }
        // window.addEventListener('scroll', console.log(111))



        // 实现每隔一秒打印1, 2, 3, 4
        // 1.使用 let 块级作用域
        // for(let i = 1; i < 5; i++){
        //     setTimeout(()=>{
        //         console.log(i);
        //     },i*1000)
        // }
        // 2.使用闭包实现
        // for(var i = 1; i < 5; i++){
        //     (function(j){
        //         setTimeout(()=>{
        //             console.log(j);
        //         },j*1000)
        //     })(i)
        // }

        
        // 使用setTimeout实现setInterval
        // function MySetInterval(fn,timeout){
        //     let flag = true
        //     function interval(){
        //         if(flag){
        //             fn()
        //             setTimeout(interval,timeout)
        //         }
        //     }
        //     setTimeout(interval,timeout)
        //     setTimeout(() => flag = false,5000)
        // }
        // MySetInterval(() => {
        //     console.log('111');
        // },1000)



        // 循环打印红黄绿
        // function red() {
        //         console.log("red");
        //     }
        // function green() {
        //     console.log("green");
        // }
        // function yellow() {
        //     console.log("yellow");
        // }
        // const task = (timer, light) => {
        //         return new Promise((resolve, reject) => {
        //             setTimeout(() => {
        //                 if (light === "red") {
        //                     red();
        //                 } else if (light === "green") {
        //                     green();
        //                 } else if (light === "yellow") {
        //                     yellow();
        //                 }
        //                 resolve(); //注意，要resolve让Promise状态变成fulfilled，不然会一直是pending，无法往下执行
        //             }, timer);
        //         });
        //     };
        // promise 实现
        // const step = () => {
        //     task(3000 , 'red')
        //         .then(() => task(2000,'green'))
        //         .then(() => task(1000,'yellow'))
        //         .then(step)  //递归
        // }
        // step()
        // async / await实现
            // const taskRunner = async () => {
            //     await task(3000, "red");
            //     await task(2000, "green");
            //     await task(1000, "yellow");
            //     taskRunner(); //递归
            // };
            // taskRunner();



        // 实现日期格式化函数
        // function dateFormat(date,format){
        //     let day = date.getDate()
        //     let month = date.getMonth() + 1
        //     let year = date.getFullYear()
        //     format = format.replace(/dd/,day)
        //     format = format.replace(/MM/,month)
        //     format = format.replace(/yyyy/,year)
        //     console.log(format);
        //     return format
        // }
        // dateFormat(new Date("2024-02-01"), "yyyy/MM/dd");
        // dateFormat(new Date("2024-03-19"), "yyyy年MM月dd日");



        // 封装一个sleep函数
        // 第一种是借助异步和定时器
        // const Sleep = (timeout) => {
        //     return new Promise((resolve) => {
        //         const timeoutHandle = setTimeout(() => {
        //             clearTimeout(timeoutHandle);
        //             resolve();
        //         }, timeout);
        //     })
        // }
        // async function testSleep(){
        //     console.log('开始执行');
        //     await Sleep(2000);
        //     console.log('执行结束');
        // }
        // testSleep()
        // 第二种是借助循环和Date
        // const sleep = (timeout) => {
        //     let now = +(new Date())
        //     while (+(new Date()) - now < timeout) {}
        // }
        // async function test(){
        //     console.log('111');
        //     await sleep(2000)
        //     console.log('222');
        // }
        // test()






    </script>
</body>
</html>